//   Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <string>
#include <vector>
#include <memory>
#include <utility>
#include <ctime>
#include <mutex>
#include <opencv2/opencv.hpp>

#include "common/model_config.h"
#include "rockchip/base/rk_predictor.h"
#include "rockchip/rkmodel_manager.h"


namespace ai {

  //SCRFD人脸检测、关键点检测后处理算法具体变量定义
  typedef struct
  {
      float cx;
      float cy;
      float stride;
  } SCRFDPoint;

  typedef struct
  {
      float ratio;
      int dw;
      int dh;
      bool flag;
  } SCRFDScaleParams;

  typedef struct
  {
      float       x1;
      float       y1;
      float       x2;
      float       y2;
      float       score;
      int         label;
      const char  *label_text;
      bool        flag; // future use.

  } Boxf;

  typedef struct
  {
      std::vector<cv::Point2f> points; // x,y
      bool flag;

  } Landmarks;

  typedef struct
  {
      Boxf box;
      Landmarks landmarks;
      bool flag;
      
  } BoxfWithLandmarks;
  //SCRFD人脸检测、关键点检测后处理算法具体变量定义

class RKScrfdPredictor : public RKPredictor {
public:
  RKScrfdPredictor(RKPackPredictor* model, RKModelManager* mng, LogInfo *lg);
  ~RKScrfdPredictor(){}

private:
  int RunDet(stream::ImageBlob* blob, std::vector<BaseInfo*>& det_infos);


  int PostProcess(std::vector<BaseInfo*>& det_infos, 
                int cur_block,
                RKModelManager* mng, 
                int md_idx);
private:
  int start_postprocess_thread_imp();

  void resize_unscale(const cv::Mat &mat, cv::Mat &mat_rs,
                            int target_height, int target_width,
                            SCRFDScaleParams &scale_params);


  void generate_points(const int target_height, const int target_width);

  void generate_bboxes_kps_single_stride(const SCRFDScaleParams &scale_params,
                                            float* score_ptr,
                                            float* bbox_ptr,
                                            float* kps_ptr,
                                            unsigned int stride,
                                            float score_threshold,
                                            float img_height,
                                            float img_width,
                                            std::vector<BoxfWithLandmarks> &bbox_kps_collection);  

  float iou_of(Boxf tbox,Boxf tb);

  void nms_bboxes_kps(std::vector<BoxfWithLandmarks> &input,
                           std::vector<BoxfWithLandmarks> &output,
                           float iou_threshold, unsigned int topk);

  void generate_bboxes_kps(const SCRFDScaleParams &scale_params,
                              std::vector<BoxfWithLandmarks> &bbox_kps_collection,
                              float** output_tensors,
                              float score_threshold, float img_height,
                              float img_width,float input_height,float input_width);

  int GetConvDetectionResult(float** output_tensors, SCRFDScaleParams scale_params, float score_threshold, float iou_threshold, int img_height, int img_width, std::vector<BaseInfo*>& det_infos, unsigned int topk, std::vector<BoxfWithLandmarks>& detected_boxes);                            

  void ParseTensor(float* out_data, int layer, 
    std::vector<cv::Rect>& boxs, std::vector<float>& scores, std::vector<int>& labels,
    std::vector<int> ori_shape, std::vector<int> feteature_shape, ModelConfig* cfg);


private:
  std::vector<float> MeshGrid;
  int HeadNum;
  int TopK = 50;
  
};

  //SCRFD人脸检测、关键点检测后处理算法具体变量定义
  static unsigned int nms_pre = 1000;
  static unsigned int max_nms = 30000;
  static unsigned int fmc = 3; // feature map count
  static bool use_kps = true;
  static unsigned int num_anchors = 2;
  static std::vector<int> feat_stride_fpn = {8, 16, 32}; // steps, may [8, 16, 32, 64, 128]   
  static std::vector<int> output_num_points = {12800, 3200, 800};
  static std::unordered_map<int, std::vector<SCRFDPoint>> center_points;
  static bool center_points_is_update = false;
  //SCRFD人脸检测、关键点检测后处理算法具体变量定义

}  // namespace hb
